//go:build windows
// +build windows

// Package dll类 备注, 由go的syscall包复制过来修改的.
package 内部类

import (
	"fmt"
	"golang.org/x/sys/windows"
	"strconv"
	"strings"
	"unsafe"
)

var (
	ntdll         = DLL载入("ntdll.dll")
	rtlGetVersion = ntdll.X命令("RtlGetVersion")
)

// X取系统版本 获取系统名称、平台版本、内核版本号
// 返回值：
// - 系统名称: 如"Microsoft Windows 10"或"Microsoft Windows 11"
// - 平台版本: 如"10.0.19041.1 Build 19041.1"
// - 内核版本号: 如10
// - 错误: 在操作过程中可能遇到的错误
// 来源 https://github.com/shirou/gopsutil
func X取系统版本() (系统名称 string, 平台版本 string, 内核版本号 int, 错误 error) {
	// GetVersionEx 在 Windows 8.1 上会返回错误的版本信息，表现为 Windows 8，如果我们没有在程序清单中声明兼容性
	// RtlGetVersion 可以绕过这一层，返回真实的 Windows 版本
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
	// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw

	// 定义操作系统版本信息结构体
	type osVersionInfoExW struct {
		dwOSVersionInfoSize uint32
		dwMajorVersion      uint32
		dwMinorVersion      uint32
		dwBuildNumber       uint32
		dwPlatformId        uint32
		szCSDVersion        [128]uint16
		wServicePackMajor   uint16
		wServicePackMinor   uint16
		wSuiteMask          uint16
		wProductType        uint8
		wReserved           uint8
	}

	// 初始化操作系统版本信息
	var osInfo osVersionInfoExW
	osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
	ret, _, 错误 := rtlGetVersion.X调用(uintptr(unsafe.Pointer(&osInfo)))
	if ret != 0 {
		return
	}

	// 从注册表获取系统名称
	var h windows.Handle
	错误 = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
	if 错误 != nil {
		return
	}
	defer windows.RegCloseKey(h)

	// 查询系统产品名称
	var bufLen uint32
	var valType uint32
	错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
	if 错误 != nil {
		return
	}
	regBuf := make([]uint16, bufLen/2+1)
	错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
	if 错误 != nil {
		return
	}
	系统名称 = windows.UTF16ToString(regBuf[:])

	// 检查是否为Windows 10，并确定是否实际上是Windows 11
	if strings.Contains(系统名称, "Windows 10") {
		错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CurrentBuildNumber`), nil, &valType, nil, &bufLen)
		if 错误 == nil {
			regBuf = make([]uint16, bufLen/2+1)
			错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CurrentBuildNumber`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
			if 错误 == nil {
				buildNumberStr := windows.UTF16ToString(regBuf[:])
				if buildNumber, err := strconv.Atoi(buildNumberStr); err == nil && buildNumber >= 22000 {
					系统名称 = strings.Replace(系统名称, "Windows 10", "Windows 11", 1)
				}
			}
		}
	}

	// 查询并附加服务包编号
	错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, nil, &bufLen)
	if 错误 == nil {
		regBuf = make([]uint16, bufLen/2+1)
		错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`CSDVersion`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
		if 错误 == nil {
			系统名称 += " " + windows.UTF16ToString(regBuf[:])
		}
	}

	// 查询并处理更新构建修订号(UBR)
	var UBR uint32
	错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`UBR`), nil, &valType, nil, &bufLen)
	if 错误 == nil {
		regBuf := make([]byte, 4)
		错误 = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`UBR`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
		copy((*[4]byte)(unsafe.Pointer(&UBR))[:], regBuf)
	}

	// 构建平台版本字符串
	平台版本 = fmt.Sprintf("%d.%d.%d.%d Build %d.%d",
		osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, UBR,
		osInfo.dwBuildNumber, UBR)

	// 提取内核版本号
	parts := strings.Split(平台版本, ".")
	if len(parts) > 4 {
		内核版本号, _ = strconv.Atoi(parts[0])
	}
	return 系统名称, 平台版本, 内核版本号, nil
}
